package com.grape.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.grape.constants.Constants;
import com.grape.utils.MenuUtils;
import com.grape.utils.StringUtils;
import com.grape.utils.ThreadLocalUtil;
import com.grape.vo.BaseVo;
import com.grape.vo.MenuVO;
import com.grape.vo.UserVO;
import com.grape.wrapper.BaseWrapper;
import com.grape.entity.SysMenu;
import com.grape.mapper.SysMenuMapper;
import com.grape.service.ISysMenuService;
import lombok.AllArgsConstructor;
import org.apache.logging.log4j.util.Strings;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 *
 * 菜单权限表 服务实现类
 *
 * @author  putao
 * @email   2628279194@qq.com
 */
@Service
@AllArgsConstructor
@Transactional(readOnly = true)
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    private final SysMenuMapper sysMenuMapper;

    private final ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 分页
     * @param baseVo    统一分页对象
     * @return          菜单权限表集合
     */
    @Override
    public List<SysMenu> listData(BaseVo baseVo) {
        QueryWrapper<SysMenu> wrapper = new BaseWrapper<SysMenu>().init();
        wrapper.like(Strings.isNotBlank(baseVo.getSearch()), "name", baseVo.getSearch());
        wrapper.eq(StringUtils.isNotBlank(baseVo.getColumnName())
                && StringUtils.isNotBlank(baseVo.getSelect()), baseVo.getColumnName(), baseVo.getSelect());
        orderByModifyTimeDesc(wrapper);
        return this.list(wrapper);
    }

    /**
     * 修改
     * @param sysMenu 菜单权限表对象
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public void updateData(SysMenu sysMenu) {
        this.baseUpdate(sysMenu);
    }

    /**
     * 新增
     * @param sysMenu   菜单权限表对象
     * @return          菜单权限表对象
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public SysMenu insertData(SysMenu sysMenu) {
        return this.baseInsert(sysMenu);
    }

    /**
     * 删除
     * @param id    单据id
     * @return      删除条数
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public int deleteData(String id) {
        return this.baseDelete(id);
    }

    /**
     * 根据id查询详情
     * @param id    菜单id
     * @return      菜单权限表对象
     */
    @Override
    public SysMenu detail(String id) {
        return this.getById(id);
    }

    /**
     * 根据角色id查询菜单
     * @param roleId    角色id
     * @return          菜单VO集合
     */
    @Override
    public List<MenuVO> getMenuByRoleId(String roleId) {
        List<SysMenu> menuList = sysMenuMapper.getMenuByRoleId(roleId);
        return handleMenuList(menuList);
    }

    /**
     * 根据当前用户查询菜单列表
     * @return      菜单VO集合
     */
    @Override
    public List<MenuVO> getMenuByUserId() {
        UserVO userVo = ThreadLocalUtil.get();
        List<SysMenu> menuList;
        if (Constants.ONE_STR.equals(userVo.getIsAdmin())) {
            menuList = sysMenuMapper.selectList(new QueryWrapper<>());
        } else {
            menuList = sysMenuMapper.getMenuByUserId(userVo.getId());
        }
        return handleMenuList(menuList);
    }

    /**
     * 列表转树形
     * @param menuList  菜单集合
     * @return          菜单VO集合
     */
    private List<MenuVO> handleMenuList(List<SysMenu> menuList) {
        if (CollectionUtil.isNotEmpty(menuList)) {
            return MenuUtils.recursionSysMenu("0", menuList);
        }
        return Collections.emptyList();
    }

    /**
     * 根据角色id查询角色菜单
     * @param roleId            角色id
     * @param parentMenuList    父菜单集合
     * @return                  菜单集合
     */
    @Override
    public List<SysMenu> getByRoleId(String roleId, List<MenuVO> parentMenuList) throws ExecutionException, InterruptedException {
        CompletableFuture<List<MenuVO>> parentMenuListFuture = CompletableFuture.supplyAsync(() -> MenuUtils.recursionSysMenu(Constants.ZERO_STR, this.sysMenuMapper.selectList(new QueryWrapper<>())), threadPoolTaskExecutor);
        CompletableFuture<List<SysMenu>> menuListFuture = CompletableFuture.supplyAsync(() -> this.sysMenuMapper.selectByRoleId(roleId), threadPoolTaskExecutor);
        CompletableFuture<Void> allTasks = CompletableFuture.allOf(parentMenuListFuture, menuListFuture);
        allTasks.join();
        parentMenuList.addAll(parentMenuListFuture.get());
        return menuListFuture.get();
    }

    /**
     * 查询所有的菜单并转树形
     * @return      菜单集合
     */
    @Override
    public List<SysMenu> listAllForTree() {
        List<SysMenu> menuList = this.list();
        if (CollectionUtil.isNotEmpty(menuList)) {
            return MenuUtils.recursionSysMenuList(Constants.ZERO_STR, menuList);
        }
        return null;
    }

    /**
     * 根据id删除菜单
     * @param id    菜单id
     * @return      删除条数
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public int deleteMenu(String id) {
        return this.sysMenuMapper.deleteById(id);
    }
}
